大家好,我們是 AI . FREE Team - 人工智慧自由團隊,這一次的鐵人賽,自由團隊將從0到1 手把手教各位讀者學會 (1)Python基礎語法 (2)Python Web 網頁開發框架 – Django (3)Python網頁爬蟲 – 周易解夢網 (4)Tensorflow AI語言模型基礎與訓練 – LSTM (5)實際部屬AI解夢模型到Web框架上。
自由團隊的成立宗旨為開發AI/新科技的學習資源,提供各領域的學習者能夠跨域學習資料科學,並透過自主學習發展協槓職涯,結合智能應用到各式領域,無論是文、法、商、管、醫領域的朋友,都可以自由的學習AI技術。
AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源
我們昨天在最後一部分已經將「古人查詢系統」的兩個 model 設計出來了,在今天,我們會看看有什麼簡單的方式可以對資料庫做新增(Create)、刪除(Delete)、修改(Update)、查看(Read)的動作。我們在今天會先使用 Shell Command的方式做到上方提到的動作,在未來幾篇會陸續提到其他種可以達到相同目的的方法,敬請期待!
在 Django 內,有很多已經被設計好可以用來呼叫資料庫裡面 data 的方法了,我們可以直接的在 Django Shell 裡面進行操作,要進入 Shell Command 會需要使用到 manage.py,所以在一開始,我們就先切換路徑至 .../DI_project(這樣才能和 manage.py 同一層目錄),然後透過 manage.py 進入 shell 介面。
Note: Shell 翻譯成中文是「殼層」的意思,其實就是一個便於大家使用特定功能的介面。
$ cd DI_project
$ python manage.py shell
大家應該會看到類似下面的介面(有沒有覺得和輸入 python 後顯示的介面很像呢)
Python 3.7.4 (default, Aug 9 2019, 18:34:13) [MSC v.1915 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
我們接著就要在 >>> 後方輸入我們的 Command 指令了。在下方將會使用 Djagno 的 Shell Command 做到增、刪、改、查的動作。其實可以把 Shell 當作是一個小小的實驗室,我們能先在這邊測試想法是否正確且符合預期,確定沒問題之後再將對應的 Command 加入專案的程式裡頭。
import
$ from demo_app.models import Ancient_People, School
在這邊又再次複習 import package 的觀念了,在 DI_project/models.py 裡面是兩個我們昨天寫好的 model(在 python 當中被視為 class),一個是 Ancient_People,另一個則是 School,因為我們等等是要對這兩個 model 做一些操作,所以在這邊要先 import 起來。
因為下面會使用到昨天提到的資料,所以我們再一次把表格列出來,等等大家就可以邊打邊copy,應該會比較快一些!(這邊順便附上英文,英文的程式相容性總是比中文高,所以之後我們都會用英文喔。)
古人(name) | 名言(statement) | 歲數(age) |
---|---|---|
孔子(Confucius) | 有朋自遠方來,不亦樂乎? 見利思義,見危受命。(Is it not delightful to have friends coming from distant quarters? ...) | 27 |
孟子(Mencius) | 獨樂樂,與人樂樂,孰樂?(A single person's joy will never measure up to the joy shared by all.) | 65 |
荀子(Xunzi) | 鍥而舍之,朽木不折;鍥而不捨,金石可鏤。(Carving something but giving up halfway, we cannot even carve rotten wood. ...) | 67 |
老子(Lao Tzu) | 治大國,若烹小鮮。(Ruling a large nation is like cooking a small delicacy.) | 18 |
莊子(Zhuangzi) | 真者,精誠之志也,不精不誠,不能動人。(The true, sincere to the same, not fine and sincere, can not move.) | 22 |
學派(school_name) | 中心價值(core_value) | 全盛時期人數(num_member) |
---|---|---|
道家(Taoism) | 人與自然的和諧相處。(Harmony between man and nature.) | 4777 |
儒家(Confucianism) | 人與人之間要「仁」與「禮」。(Benevolence and courtesy between people.) | 3952 |
全部都列出來之後發現自己好像在傳教(笑)
大家先確定自己有在Django Shell 裡面,而且已經有 import 兩個 models 了。準備好之後,我們先看看目前擁有的資料,在我們都還沒有加入的情況下,預計什麼都沒有。
>>> School.objects.all()
<QuerySet []>
回傳的 schools 是一個空的 QuerySet,符合我們的預期。我們接著加入道家的資料。
>>> School.objects.create(school_name="Taoism", core_value="Harmony between man and nature.", num_member=4777)
<School: School object (1)>
這邊的 School 是在上方我們 import 進來的其中一個 model,而在 create 這個方法裡面,我們需要各別提供一個值給最初在設計 model 的時候設計的 Field,像是「把”Taoism” 這個值 給 school_name 這個 Field」、「把 4777 這個值 給 num_member 這個 Field」。這邊如果大家有點疑惑的,就把 models.py 打開好好研究一番吧!
回傳的 School object,其中的 1 表示它的 id 是 ,並不是目前一共有1筆資料喔。如果我在新增這個 School Object 之前有建立5筆資料,然後再刪掉的話,這邊會出現的數字就會是6了,所以注意一下,這邊的數字表示是 id,不是共有幾筆資料。總之,我們也把另一個學派(儒家)也加進資料庫吧。
>>> School.objects.create(school_name="Confucianism", core_value="Benevolence and courtesy between people.", num_member=3952)
<School: School object (2)>
>>> School.objects.all()
<QuerySet [<School: School object (1)>, <School: School object (2)>]>
在新增了儒家的資料之後再次查看目前有的所有 School Object,確實只有剛剛加的兩筆。不過這邊有個地方可以稍微修改一下,我們發現回傳的兩個 School Object 並不直觀,我們希望他可以回傳兩個字串,先退出 Django Shell Command 介面。
$ exit()
我們開啟 demo_app/ models.py 並在每個 class 最下方加入一個 def
,目的就是希望 queryset 可以回傳直觀的內容,也就是該古人的名字(name),或是該學派的名字(school_name)。
from django.db import models
class School(models.Model):
# 學派名稱
school_name = models.CharField(max_length=10)
# 中心價值
core_value = models.CharField(max_length=100)
# 人數
num_member = models.IntegerField()
def __str__(self):
return self.school_name
class Ancient_People(models.Model):
# 學派
school = models.ForeignKey(School, on_delete=models.CASCADE)
# 名字
name = models.CharField(max_length=10)
# 名言
statement = models.CharField(max_length=100)
# 歲數
age = models.IntegerField()
def __str__(self):
return self.name
這邊用到 self
,大家應該沒有很陌生吧,如果 function
(ex: def __str__
) 想要 access 到 class
(ex: Ancient_People
) 內的變數,就需要用 self
去找到 class
內部的變數喔。
每一次進入 shell 都需要重新 import 一次 models,但資料的部分還是會保留著,不過因為我們剛剛有去多加兩個 def,所以回傳的值就會不太一樣了。
>>> from demo_app.models import School, Ancient_People
>>> School.objects.all()
<QuerySet [<School: Taoism>, <School: Confucianism>]>
我們在這邊看到的 Taoism 和 Confucianism,是不是就比 School Object (1) 和 (2) 直觀許多了呢!
到現在,我們都還沒有建立針對 Ancient_People 的資料,我們馬上來按照上面的方式加加看。會出錯。
>>> Ancient_People.objects.create(name="Confucius", statement="Is it not delightful to have friends coming from distant quarters? ...", age=27)
.
.
sqlite3.IntegrityError: NOT NULL constraint failed: demo_app_ancient_people.school_id
此時會有錯誤,會發生這個錯誤是因為我們有在 Ancient_People 添加一行關於 Foreign Key 的設定,School 和 Ancient_People 之間是有依存關係的。在目前的設定而言,Ancient_Peolple 在被建立時會需要加入已經存在的 School Object,所以我們要換一種方式建立 Ancient_People 的資料。
我們先透過 get
的方式將儒家(Confucianism)資料取出(因為孔子是儒家學派的),並 assign 給一個變數(demo1, demo2, ...)。
>>> demo1 = School.objects.get(school_name="Confucianism")
>>> demo2 = School.objects.get(core_value="Benevolence and courtesy between people.")
>>> demo3 = School.objects.get(num_member=3952)
>>> demo4 = School.objects.get(id=2)
>>> demo1 # demo2, demo3, demo4 都會回傳一樣的東西
<School: Confucianism>
然後再利用這個透過 get
得到的儒家 School Object 去添加 Ancient_People 的資料。
>>> demo1.ancient_people_set.create(name="Confucius", statement="Is it not delightful to have friends coming from distant quarters? ...", age=27)
<Ancient_People: Confucius>
>>> Ancient_People.objects.all()
<QuerySet [<Ancient_People: Confucius>]>
注意到我們在 demo1 後面是使用 ancient_people_set
,ancient_people 是 class 名稱的小寫版本(i.e. class 名稱是 Ancient_People,是大寫的),這個是在我們給定 ForeignKey 的時候就被 Django 預設好的,而 _set
也,表示 Django 預想到 demo1 這個 School Object 應該要有好幾個 Ancient_People。實際上的確也符合我們的使用情境,儒家(School)確實有好幾個古人(Ancient_People)在裡面。
大家接著可以順便也把道家的資料建立起來,然後再接著補進老子和莊子的資料。
假設我們想要修改道家的中心思想,將最後的標點符號改成驚嘆號(!),那該怎麼做呢?
>>> Taoism = School.objects.get(school_name="Taoism")
>>> Taoism.core_value
'Harmony between man and nature.' # 原本是句號
>>> Taoism.core_value = 'Harmony between man and nature!' #改成驚嘆號
>>> Taoism.save() # 儲存更動
>>> test_result = School.objects.get(school_name="Taoism")
>>> test_result.core_value
'Harmony between man and nature!' #真的有變成驚嘆號
相當好理解,我們一樣會需要先 get
到目標 object 然後 assign 給一個變數(i.e. Taoism),接著我們可以直接在 . 後面加上 Field (i.e. core_value) 來做到觀看值和更動值的行為。
在這邊就只要先 get
到,然後 delete
就完事了。延續使用上方(修改)最後用到的 test_result。
>>> test_result.delete()
(1, {'demo_app.School': 1})
>>> School.objects.all()
<QuerySet [<School: Confucianism>]>
這個時候,若再去觀察 School Object 會發現其回傳值會變少一筆。
在觀看明天的內容前,想先請大家將2個學派,5個古人都加到資料庫裡面,大家可以順便當作複習,這些資料在明天會使用到喔!
我們今天使用了 Django Shell Command 對資料庫做了增刪改查的行為,其實在這篇文章提到的也只是一部分的指令而已,如果大家還想要看看有什麼其他方式可以做到查詢,推薦可以點進參考連結喔! 在明天,我們會去調整 view.py 的設計,讓網頁呈現出資料庫內有的資料。
自由團隊 官方網站:https://aifreeblog.herokuapp.com/
自由團隊 Github:https://github.com/AI-FREE-Team/
自由團隊 粉絲專頁:https://www.facebook.com/AI.Free.Team/
自由團隊 IG:https://www.instagram.com/aifreeteam/
自由團隊 Youtube:https://www.youtube.com/channel/UCjw6Kuw3kwM_il39NTBJVTg/
文章同步發布於:自由團隊部落格
(想看更多文章?學習更多AI知識?敬請鎖定自由團隊的頻道!)